package cn.happiness.frog.skill.xiaoai;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@NoArgsConstructor
@Data
public class Request {

	@JsonProperty("version")
	private String version = "1.0";
	@JsonProperty("session")
	private SessionDTO session;
	@JsonProperty("request")
	private RequestDTO request;
	@JsonProperty("query")
	private String query;
	@JsonProperty("context")
	private ContextDTO context;

	public String getIntentName() {
		return getSlotInfo()
				.map(RequestDTO.SlotInfoDTO::getIntentName)
				.orElse(null);
	}

	public String getSlotValue(String name) {
		List<RequestDTO.SlotInfoDTO.SlotsDTO> slots = getSlotInfo()
				.map(slotInfo -> Optional.ofNullable(slotInfo.getSlots()).orElse(new ArrayList<>()))
				.orElse(new ArrayList<>());
		return slots
				.stream()
				.filter(slot -> StringUtils.equals(name, slot.getName()))
				.findFirst()
				.map(RequestDTO.SlotInfoDTO.SlotsDTO::getValue)
				.orElse(null);

	}

	private Optional<RequestDTO.SlotInfoDTO> getSlotInfo() {
		return Optional.ofNullable(request)
				.flatMap(req -> Optional.ofNullable(req.getSlotInfo()));
	}

	@NoArgsConstructor
	@Data
	public static class SessionDTO {
		@JsonProperty("is_new")
		private Boolean isNew;
		@JsonProperty("session_id")
		private String sessionId;
		@JsonProperty("application")
		private ApplicationDTO application;
		@JsonProperty("user")
		private UserDTO user;

		@NoArgsConstructor
		@Data
		public static class ApplicationDTO {
			@JsonProperty("app_id")
			private String appId;
		}

		@NoArgsConstructor
		@Data
		public static class UserDTO {
			@JsonProperty("user_id")
			private String userId;
			@JsonProperty("is_user_login")
			private Boolean isUserLogin;
			@JsonProperty("gender")
			private String gender;
		}
	}

	@NoArgsConstructor
	@Data
	public static class RequestDTO {
		@JsonProperty("type")
		private Integer type;
		@JsonProperty("request_id")
		private String requestId;
		@JsonProperty("timestamp")
		private Long timestamp;
		@JsonProperty("intent")
		private IntentDTO intent;
		@JsonProperty("locale")
		private String locale;
		@JsonProperty("slot_info")
		private SlotInfoDTO slotInfo;
		@JsonProperty("is_monitor")
		private Boolean isMonitor;

		@NoArgsConstructor
		@Data
		public static class IntentDTO {
			@JsonProperty("query")
			private String query;
			@JsonProperty("score")
			private Integer score;
			@JsonProperty("complete")
			private Boolean complete;
			@JsonProperty("domain")
			private String domain;
			@JsonProperty("confidence")
			private Integer confidence;
			@JsonProperty("skillType")
			private String skillType;
			@JsonProperty("sub_domain")
			private String subDomain;
			@JsonProperty("app_id")
			private String appId;
			@JsonProperty("request_type")
			private String requestType;
			@JsonProperty("need_fetch_token")
			private Boolean needFetchToken;
			@JsonProperty("is_direct_wakeup")
			private Boolean isDirectWakeup;
			@JsonProperty("slots")
			private String slots;
			@JsonProperty("recall_method")
			private String recallMethod;
		}

		@NoArgsConstructor
		@Data
		public static class SlotInfoDTO {
			@JsonProperty("intent_name")
			private String intentName;
			@JsonProperty("slots")
			private List<SlotsDTO> slots;

			@NoArgsConstructor
			@Data
			public static class SlotsDTO {
				@JsonProperty("name")
				private String name;
				@JsonProperty("value")
				private String value;
				@JsonProperty("raw_value")
				private String rawValue;
			}
		}
	}

	@NoArgsConstructor
	@Data
	public static class ContextDTO {
		@JsonProperty("device_id")
		private String deviceId;
		@JsonProperty("user_agent")
		private String userAgent;
		@JsonProperty("device_category")
		private String deviceCategory;
		@JsonProperty("in_exp")
		private Boolean inExp;
		@JsonProperty("client_protocol_version")
		private String clientProtocolVersion;
	}
}
